#include "reactor/channel.hpp"
#include "reactor/event_loop.hpp"
#include <sys/epoll.h>
#include <iostream>

namespace reactor {

const int Channel::kNoneEvent = 0;
const int Channel::kReadEvent = EPOLLIN | EPOLLPRI;
const int Channel::kWriteEvent = EPOLLOUT;

Channel::Channel(EventLoop* loop, int fd)
    : _loop(loop),
      _fd(fd),
      _events(0),
      _revents(0) {}

Channel::~Channel() {}

void Channel::handleEvent() {
    if ((_revents & EPOLLHUP) && !(_revents & EPOLLIN)) {
        if (_closeCallback) _closeCallback();
    }
    if (_revents & (EPOLLERR)) {
        if (_errorCallback) _errorCallback();
    }
    if (_revents & (EPOLLIN | EPOLLPRI | EPOLLRDHUP)) {
        if (_readCallback) _readCallback();
    }
    if (_revents & EPOLLOUT) {
        if (_writeCallback) _writeCallback();
    }
}

void Channel::enableReading() {
    _events |= kReadEvent;
    update();
}

void Channel::disableReading() {
    _events &= ~kReadEvent;
    update();
}

void Channel::enableWriting() {
    _events |= kWriteEvent;
    update();
}

void Channel::disableWriting() {
    _events &= ~kWriteEvent;
    update();
}

void Channel::disableAll() {
    _events = kNoneEvent;
    update();
}

bool Channel::isWriting() const {
    return _events & kWriteEvent;
}

void Channel::remove() {
    _loop->removeChannel(this);
}

void Channel::update() {
    _loop->updateChannel(this);
}

} // namespace reactor
